#import "FlutterXunfei.h"

#import "IFlyMSC/IFlyMSC.h"
#import "iflyMSC/IFlySpeechConstant.h"
#import "iflyMSC/IFlySpeechUtility.h"
#import "iflyMSC/IFlySpeechSynthesizer.h"
#import "iflyMSC/IFlySpeechSynthesizerDelegate.h"
#import "iflyMSC/IFlySpeechRecognizer.h"
#import "iflyMSC/IFlySpeechRecognizerDelegate.h"

#import "ISRDataHelper.h"

@interface NSError (FlutterError)
@property(readonly, nonatomic) FlutterError *flutterError;
@end

@implementation NSError (FlutterError)
- (FlutterError *)flutterError {
    return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %d", (int)self.code]
                               message:self.domain
                               details:self.localizedDescription];
}
@end

@implementation FlutterXunfei
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"flutterXunfei" binaryMessenger:[registrar messenger]];
  FlutterXunfei* instance = [[FlutterXunfei alloc] init];
  
  instance.channel = channel;
    
  [registrar addMethodCallDelegate:instance channel:channel];
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    
    // 语音识别
    if([@"initIat" isEqualToString:call.method]){
        [self initIat:call result:result];
    }else if([@"startIat" isEqualToString:call.method]){
        [self startIat:call result:result];
    }else if([@"stopIat" isEqualToString:call.method]){
        [self stopIat:call result:result];
    }else if([@"cancelIat" isEqualToString:call.method]){
        [self cancelIat:call result:result];
    }else
    
        
    // 语音唤醒
    if([@"initIvw" isEqualToString:call.method]){
        [self initIvw:call result:result];
    }else if([@"openIvw" isEqualToString:call.method]){
        [self openIvw:call result:result];
    }else if([@"closeIvw" isEqualToString:call.method]){
        [self closeIvw:call result:result];
    }

}

/**
 初始化讯飞语音识别
 */
-(void) initIat:(FlutterMethodCall*)call result:(FlutterResult)result{
    NSDictionary *arguments = call.arguments;
    NSString *APPid = arguments[@"APPid"];
    NSString *initString = [[NSString alloc] initWithFormat:@"appid=%@",APPid];
    [IFlySpeechUtility createUtility:initString];
    
    _iFlySpeechRecognizer = [IFlySpeechRecognizer sharedInstance];
    _iFlySpeechRecognizer.delegate = self;
    
    [_iFlySpeechRecognizer setParameter:@"" forKey:[IFlySpeechConstant PARAMS]]; //清空所有参数
    [_iFlySpeechRecognizer setParameter:@"iat" forKey:[IFlySpeechConstant IFLY_DOMAIN]]; // 设置听写模式
    [_iFlySpeechRecognizer setParameter:@"cloud" forKey:[IFlySpeechConstant ENGINE_TYPE]];// 设置听写引擎
    [_iFlySpeechRecognizer setParameter:@"json" forKey: [IFlySpeechConstant RESULT_TYPE]];// 返回结果格式
    [_iFlySpeechRecognizer setParameter:@"4000" forKey:[IFlySpeechConstant VAD_BOS]];// 前端静音时长
    [_iFlySpeechRecognizer setParameter:@"1800" forKey:[IFlySpeechConstant VAD_EOS]];//后端静音时长
    [_iFlySpeechRecognizer setParameter:@"1" forKey:[IFlySpeechConstant ASR_PTT]];// 自动添加标点
    
    NSDictionary *object = @{
        @"success" :@"true",
        @"message" : @"初始化成功",
        @"code":@"0",
        @"type":@"initIat"
    };
    
    [_channel invokeMethod:@"initResult" arguments: object];

}

/**
 开启语音识别
 */
-(void) startIat:(FlutterMethodCall*)call result:(FlutterResult)result{
    if (_iFlySpeechRecognizer == nil) {
        FlutterError *error =  [FlutterError errorWithCode: @"9999" message:@"开启语音识别失败" details:@"未初始化语音识别"];
        result(error);
    }
    BOOL ret = [_iFlySpeechRecognizer startListening];
    if(ret){
        result(@0);
    }else{
        FlutterError *error =  [FlutterError errorWithCode: @"9999" message:@"开启语音识别失败" details:@"开启语音识别失败"];
        result(error);
    }
}

/**
 停止语音识别
 */
-(void) stopIat:(FlutterMethodCall*)call result:(FlutterResult)result{
    if(_iFlySpeechRecognizer == nil){
        FlutterError *error =  [FlutterError errorWithCode: @"9999" message:@"开启语音识别失败" details:@"未初始化语音识别"];
        result(error);
    }
    [_iFlySpeechRecognizer stopListening];
    result(@0);
}

/**
 取消语音识别
 */
-(void) cancelIat:(FlutterMethodCall*)call result:(FlutterResult)result{
    if(_iFlySpeechRecognizer == nil){
        FlutterError *error =  [FlutterError errorWithCode: @"9999" message:@"开启语音识别失败" details:@"未初始化语音识别"];
        result(error);
    }
    [_iFlySpeechRecognizer cancel];
    result(@0);
}

/**
 初始化语音唤醒
 */
-(void) initIvw:(FlutterMethodCall*)call result:(FlutterResult)result{
    NSDictionary *arguments = call.arguments;
    NSString *APPid = arguments[@"APPid"];
    NSString *initString = [[NSString alloc] initWithFormat:@"appid=%@",APPid];
    [IFlySpeechUtility createUtility:initString];
    
    _iflyVoiceWakeuper =  [IFlyVoiceWakeuper sharedInstance];
    _iflyVoiceWakeuper.delegate = self;
    
    [_iflyVoiceWakeuper setParameter:@"1450" forKey:@"ivw_threshold"]; //唤醒门限值
    [_iflyVoiceWakeuper setParameter:@"wakeup" forKey:@"ivw_sst"]; // 唤醒模式
    [_iflyVoiceWakeuper setParameter:@"1" forKey:@"keep_alive"];// 保持持续唤醒
    [_iflyVoiceWakeuper setParameter:@"0" forKey:@"ivwnet_mode"];// 开启关闭闭环优化模式
    
    NSString *mainBundlePath = [NSBundle mainBundle].bundlePath;
    NSString *wordsBundlePath = [NSString stringWithFormat:@"%@/%@",mainBundlePath,@"WakeWords.bundle"];
    NSBundle *wordsBundle = [NSBundle bundleWithPath:wordsBundlePath];
    NSString *wordsPath = [[NSString alloc] initWithFormat:@"%@/ivw/%@.jet",wordsBundle.resourcePath,APPid];
    NSString *wordsResourcePath = [IFlyResourceUtil generateResourcePath:wordsPath];
    
    NSLog(@"资源文件%@",wordsResourcePath);
    [_iflyVoiceWakeuper setParameter:wordsResourcePath forKey:@"ivw_res_path"];
}

/**
 开启语音唤醒
 */
-(void) openIvw:(FlutterMethodCall*)call result:(FlutterResult)result{
    if (_iflyVoiceWakeuper == nil) {
        FlutterError *error =  [FlutterError errorWithCode: @"9999" message:@"开启语音唤醒失败" details:@"未初始化语音唤醒"];
        result(error);
    }
    BOOL ret = [_iflyVoiceWakeuper startListening];
    if(ret){
        result(@0);
    }else{
        FlutterError *error =  [FlutterError errorWithCode: @"9999" message:@"开启语音唤醒失败" details:@"开启语音唤醒失败"];
        result(error);
    }

}

/**
 关闭语音唤醒
 */
-(void) closeIvw:(FlutterMethodCall*)call result:(FlutterResult)result{
    if(_iflyVoiceWakeuper == nil){
        FlutterError *error =  [FlutterError errorWithCode: @"9999" message:@"关闭语音唤醒失败" details:@"未初始化语音唤醒"];
        result(error);
    }
    [_iflyVoiceWakeuper stopListening];
    result(@0);
}



#pragma mark - IFlyVoiceWakeuperDelegate

- (void)onResult:(NSMutableDictionary *)resultDic{
    
    [_channel invokeMethod:@"onIvwResult" arguments: resultDic];
    
    NSString *sst = [resultDic objectForKey:@"sst"];
    NSNumber *wakeId = [resultDic objectForKey:@"id"];
    NSString *score = [resultDic objectForKey:@"score"];
    NSString *bos = [resultDic objectForKey:@"bos"];
    NSString *eos = [resultDic objectForKey:@"eos"];
    NSString *keyword = [resultDic objectForKey:@"keyword"];

    NSLog(@"【KEYWORD】   %@",keyword);
    NSLog(@"【SST】   %@",sst);
    NSLog(@"【ID】    %@",wakeId);
    NSLog(@"【SCORE】 %@",score);
    NSLog(@"【EOS】   %@",eos);
    NSLog(@"【BOS】   %@",bos);

    NSLog(@"");
    NSMutableString *result = [[NSMutableString alloc] init];
    [result appendFormat:@"\n"];

    [result appendFormat:@"【KEYWORD】        %@\n",keyword];
    [result appendFormat:@"【SST】        %@\n",sst];
    [result appendFormat:@"【ID】         %@\n",wakeId];
    [result appendFormat:@"【SCORE】      %@\n",score];
    [result appendFormat:@"【EOS】        %@\n",eos];
    [result appendFormat:@"【BOS】        %@\n",bos];

    NSLog(@"%@",result);
}

#pragma mark - IFlySpeechRecognizerDelegate

/**
 volume callback,range from 0 to 30.
 **/
- (void) onVolumeChanged: (int)volume
{
    if (self.isCanceled) {
        return;
    }

//    NSString * vol = [NSString stringWithFormat:@"%@：%d", NSLocalizedString(@"T_RecVol", nil),volume];
//    [_popUpView showText: vol];
}


/**
 Beginning Of Speech
 **/
- (void) onBeginOfSpeech
{
    NSLog(@"onBeginOfSpeech");
}

/**
 End Of Speech
 **/
- (void) onEndOfSpeech
{
    NSLog(@"onEndOfSpeech");
}


/**
 recognition session completion, which will be invoked no matter whether it exits error.
 error.errorCode =
 0     success
 other fail
 **/
- (void) onCompleted:(IFlySpeechError *) error
{
    NSLog(@"%s",__func__);
    NSString *text ;
    if (self.isCanceled) {
        text = NSLocalizedString(@"T_ISR_Cancel", nil);
    } else if (error.errorCode != 0 ) {
        text = [NSString stringWithFormat:@"Error：%d %@", error.errorCode,error.errorDesc];
        NSDictionary *retDictionary = @{
            @"error" : text
        };
        [_channel invokeMethod:@"onReceiveSpeechText" arguments: retDictionary];
    }
}

/**
 result callback of recognition without view
 results：recognition results
 isLast：whether or not this is the last result
 **/
- (void) onResults:(NSArray *) results isLast:(BOOL)isLast
{
    NSMutableString *resultString = [[NSMutableString alloc] init];
    NSDictionary *dic = results[0];
    
    for (NSString *key in dic) {
        [resultString appendFormat:@"%@",key];
    }
    
    NSString * resultFromJson =  nil;
    

    resultFromJson = [ISRDataHelper stringFromJson:resultString];

    
    NSLog(@"resultsFromJson=%@",resultFromJson);
    
    NSDictionary *retDictionary = @{
        @"text" : resultFromJson,
        @"isLast" : [NSNumber numberWithBool:isLast],
        @"type": [NSNumber numberWithInt:1]
    };
    
    [_channel invokeMethod:@"onIatResult" arguments: retDictionary];
    
}



/**
 result callback of recognition with view
 resultArray：recognition results
 isLast：whether or not this is the last result
 **/
- (void)onResult:(NSArray *)resultArray isLast:(BOOL)isLast
{
    NSMutableString *resultString = [[NSMutableString alloc] init];
    NSDictionary *dic = [resultArray objectAtIndex:0];
    
    for (NSString *key in dic) {
        [resultString appendFormat:@"%@",key];
    }
    
    NSString * resultFromJson =  nil;
    
    resultFromJson = [NSString stringWithFormat:@"%@",resultString];//;[ISRDataHelper stringFromJson:resultString];
    
    NSLog(@"resultFromJson=%@",resultFromJson);
    
    NSDictionary *retDictionary = @{
        @"text" : resultFromJson,
        @"isLast" : [NSNumber numberWithBool:isLast],
        @"type": [NSNumber numberWithInt:2]
    };
    
    [_channel invokeMethod:@"onReceiveSpeechText" arguments: retDictionary];
    
}



/**
 callback of canceling recognition
 **/
- (void) onCancel
{
    NSLog(@"Recognition is cancelled");
}

@end
